﻿using Sustainalytics.ESG.Entities;
using Sustainalytics.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Sustainalytics.CRT.Synchronization
{
    public static class PeerOrderingPolicy
    {
        private const double TOLERANCE = 1e-16;

        public static RPCorporateScore[] GetScores(
            IEnumerable<RPCorporateScore> list,
            Expression<Func<RPCorporateScore, object>> expressionToOrderBy)
        {
            var result = list.OrderByDescending(expressionToOrderBy.Compile()).Take(5).ToArray();

            result.PrevCurrentZip(FillRankPolicy(result));
            return result;
        }

        private static Action<RPCorporateScore, RPCorporateScore> FillRankPolicy(IEnumerable<RPCorporateScore> allScores)
        {
            return (prev, item) =>
            {
                if (prev != null)
                {
                    if (IsScoreEqual(prev, item))
                    {
                        item.Rank = prev.Rank;
                    }
                    else
                    {
                        item.Rank = prev.Rank + allScores.Count(x => IsScoreEqual(x, item));
                    }
                }
                else
                {
                    item.Rank = 1;
                }
            };
        }

        private static bool IsScoreEqual(RPCorporateScore left, RPCorporateScore right)
        {
            return Math.Abs(left.Score - right.Score) < TOLERANCE;
        }
    }
}